#include <chrono>
#include <sstream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <modules.h>
#include <cnotify.h>
#include <commands.h>
#include <cronManager.h>
#include <timerManager.h>
#include <taskManager.h>
#include <cliManager.h>
#include <framework.h>
#include <jobQueue.h>
#include <utils.h>
#include <log.h>
#include <nlohmann/json.hpp>

// Cron field indices (avoids magic numbers)
LOCAL const int CRON_MINUTE = 0;    // Minute field index
LOCAL const int CRON_HOUR = 1;      // Hour field index
LOCAL const int CRON_DAY = 2;       // Day of month field index
LOCAL const int CRON_MONTH = 3;     // Month field index
LOCAL const int CRON_WEEKDAY = 4;   // Weekday field index
LOCAL const int CRON_FIELD_NUM = 5;   // cron field number
#define DEFAULT_CRON_FILE "crontask.json"

// Helper structure: Stores detailed current time info
struct CurrentTimeInfo
{
    int year;    // e.g., 2023
    int month;   // 1-12
    int day;     // 1-31
    int hour;    // 0-23
    int minute;  // 0-59
    int weekday; // 0=Sunday, 6=Saturday (matches Cron definition)
};

LOCAL bool validate_cron(const char* cronExpr);
LOCAL const cli::CliCmd gCronCommands[] =
{
    {
        "cron-task-add",
        "Add a cron job (format: cron-task-add -c \"0 * * * *\" -t /home/user/task.sh)",
        MODULE_CRON_MGR,
        CMD_CRON_ADD,
        {
            {
                "name",
                "n",
                "Cron task name",
                true,
                NULLSTR,
                true,
                nullptr
            },
            {
                "cron",
                "c",
                "Cron expression (format: min hour day month week)",
                true,
                NULLSTR,
                true,
                validate_cron
            },
            {
                "task",
                "t",
                "Task script path",
                true,
                NULLSTR,
                true,
                nullptr
            }
        }
    },
    {
        "cron-task-remove",
        "Remove a cron job by index",
        MODULE_CRON_MGR,
        CMD_CRON_REMOVE,
        {
            {
                "name",
                "n",
                "Cron task name (use cron-task-list to check)",
                true,
                NULLSTR,
                true,
                nullptr
            }
        }
    },
    {
        "cron-task-list",
        "Show all cron job",
        MODULE_CRON_MGR,
        CMD_CRON_LIST,
    }
};

// Month name to number mapping (Jan -> 1, ..., Dec -> 12)
LOCAL const std::unordered_map<std::string, int> month_map =
{
    {"jan", 1},  {"feb", 2},  {"mar", 3},  {"apr", 4},
    {"may", 5},  {"jun", 6},  {"jul", 7},  {"aug", 8},
    {"sep", 9},  {"oct", 10}, {"nov", 11}, {"dec", 12}
};

// Weekday name to number mapping (Sun -> 0, ..., Sat -> 6)
LOCAL const std::unordered_map<std::string, int> weekday_map =
{
    {"sun", 0}, {"mon", 1}, {"tue", 2}, {"wed", 3},
    {"thu", 4}, {"fri", 5}, {"sat", 6}
};

// Check if string contains only digits
LOCAL bool is_all_digits(const std::string& s)
{
    if (s.empty()) return false;
    for (char c : s)
    {
        if (!std::isdigit(static_cast<unsigned char>(c)))
            return false;
    }
    return true;
}

// Convert month/weekday name or digit string to numerical value
// Returns -1 on failure
LOCAL int parse_field_value(const std::string& s, bool is_month, bool is_weekday)
{
    // Handle numeric values
    if (is_all_digits(s))
        return std::stoi(s);

    // Handle case-insensitive name conversion
    std::string lower_str = s;
    std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), ::tolower);

    if (is_month && month_map.count(lower_str))
        return month_map.at(lower_str);

    if (is_weekday && weekday_map.count(lower_str))
        return weekday_map.at(lower_str);

    return -1;  // Invalid value
}

// Helper function: Get detailed current time information
LOCAL CurrentTimeInfo get_current_time_info()
{
    auto now = std::chrono::system_clock::now();
    std::time_t now_time = std::chrono::system_clock::to_time_t(now);
    std::tm local_tm;

    utils::localtime_rs(&local_tm, &now_time);

    return {
        local_tm.tm_year + 1900,  // tm_year is years since 1900
        local_tm.tm_mon + 1,      // tm_mon is 0-11, convert to 1-12
        local_tm.tm_mday,
        local_tm.tm_hour,
        local_tm.tm_min,
        local_tm.tm_wday          // 0=Sunday (matches Cron)
    };
}

// Helper function: Calculate last day of the given month (accounts for leap years)
LOCAL int get_last_day_of_month(int year, int month)
{
    if (month == 2)
    {
        bool is_leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
        return is_leap ? 29 : 28;
    }
    return (month == 4 || month == 6 || month == 9 || month == 11) ? 30 : 31;
}

// Helper function: Calculate last occurrence of target weekday in the month
LOCAL int get_last_weekday_of_month(int year, int month, int target_weekday)
{
    int last_day = get_last_day_of_month(year, month);

    // Calculate weekday of the last day
    std::tm tm = {};
    tm.tm_year = year - 1900;
    tm.tm_mon = month - 1;
    tm.tm_mday = last_day;
    std::mktime(&tm);
    int last_day_weekday = tm.tm_wday;

    // Calculate backward from last day
    int diff = (last_day_weekday - target_weekday + 7) % 7;
    return last_day - diff;
}

// Helper function: Get min/max range for specific cron field type
LOCAL std::pair<int, int> get_field_range(int field_type)
{
    switch (field_type)
    {
    case CRON_MINUTE:  return std::make_pair(0, 59);
    case CRON_HOUR:    return std::make_pair(0, 23);
    case CRON_DAY:     return std::make_pair(1, 31);
    case CRON_MONTH:   return std::make_pair(1, 12);
    case CRON_WEEKDAY: return std::make_pair(0, 6);
    default:           return std::make_pair(0, 0);
    }
}

// Core helper: Parse a single sub-field (unified logic for all field types)
LOCAL void parse_sub_field(const std::string& sub,
    int field_type,
    const CurrentTimeInfo& time_info,
    std::vector<int>& values)
{
    // Handle wildcard (*)
    if (sub == "*")
    {
        auto [min, max] = get_field_range(field_type);
        for (int i = min; i <= max; ++i)
            values.push_back(i);
        return;
    }

    // Handle step values (e.g., */15, 3-23/2)
    size_t slash_pos = sub.find('/');
    if (slash_pos != std::string::npos)
    {
        std::string left = sub.substr(0, slash_pos);
        std::string step_str = sub.substr(slash_pos + 1);

        if (left.empty() || step_str.empty() || !is_all_digits(step_str))
            return; // Invalid format (already validated earlier)

        int step = std::stoi(step_str);
        if (step <= 0) return;

        int start, end;
        if (left == "*")
        {
            auto [min, max] = get_field_range(field_type);
            start = min;
            end = max;
        }
        else
        {
            // Handle range in step left part (e.g., 3-23/2)
            size_t dash_pos = left.find('-');
            if (dash_pos == std::string::npos)
            {
                // Single value before step (e.g., 5/2)
                start = parse_field_value(left, field_type == CRON_MONTH, field_type == CRON_WEEKDAY);
                end = start;
            }
            else
            {
                std::string start_str = left.substr(0, dash_pos);
                std::string end_str = left.substr(dash_pos + 1);
                start = parse_field_value(start_str, field_type == CRON_MONTH, field_type == CRON_WEEKDAY);
                end = parse_field_value(end_str, field_type == CRON_MONTH, field_type == CRON_WEEKDAY);
            }
        }

        if (start == -1 || end == -1 || start > end) return;
        for (int i = start; i <= end; i += step)
            values.push_back(i);
        return;
    }

    // Handle range values (e.g., 1-5)
    size_t dash_pos = sub.find('-');
    if (dash_pos != std::string::npos)
    {
        std::string start_str = sub.substr(0, dash_pos);
        std::string end_str = sub.substr(dash_pos + 1);

        int start = parse_field_value(start_str, field_type == CRON_MONTH, field_type == CRON_WEEKDAY);
        int end = parse_field_value(end_str, field_type == CRON_MONTH, field_type == CRON_WEEKDAY);

        if (start == -1 || end == -1 || start > end) return;
        for (int i = start; i <= end; ++i)
            values.push_back(i);
        return;
    }

    // Handle weekday # syntax (e.g., 3#2 = 2nd Tuesday)
    if (field_type == CRON_WEEKDAY)
    {
        size_t hash_pos = sub.find('#');
        if (hash_pos != std::string::npos)
        {
            std::string day_str = sub.substr(0, hash_pos);
            std::string nth_str = sub.substr(hash_pos + 1);

            if (day_str.empty() || nth_str.empty() || !is_all_digits(nth_str))
                return;

            int day = parse_field_value(day_str, false, true);
            int nth = std::stoi(nth_str);
            if (day == -1 || nth < 1 || nth > 5)
                return;

            // Calculate nth occurrence of target weekday in month
            std::tm tm = {};
            tm.tm_year = time_info.year - 1900;
            tm.tm_mon = time_info.month - 1;
            tm.tm_mday = 1;
            std::mktime(&tm);

            int count = 0;
            while (tm.tm_mon == (time_info.month - 1))
            {
                if (tm.tm_wday == day)
                {
                    if (++count == nth)
                    {
                        values.push_back(day);
                        break;
                    }
                }
                tm.tm_mday++;
                std::mktime(&tm);
            }
            return;
        }
    }

    // Handle L (last day/weekday)
    if (sub == "L")
    {
        if (field_type == CRON_DAY)
        {
            values.push_back(get_last_day_of_month(time_info.year, time_info.month));
        }
        else if (field_type == CRON_WEEKDAY)
        {
            values.push_back(time_info.weekday);
        }
        return;
    }

    // Handle W (nearest weekday, e.g., 15W)
    if (field_type == CRON_DAY)
    {
        size_t w_pos = sub.find('W');
        if (w_pos != std::string::npos)
        {
            std::string day_str = sub.substr(0, w_pos);
            if (day_str.empty() || !is_all_digits(day_str))
                return;

            int target_day = std::stoi(day_str);
            int last_day = get_last_day_of_month(time_info.year, time_info.month);
            if (target_day < 1 || target_day > last_day)
                return;

            // Calculate adjusted weekday
            std::tm tm = {};
            tm.tm_year = time_info.year - 1900;
            tm.tm_mon = time_info.month - 1;
            tm.tm_mday = target_day;
            std::mktime(&tm);

            int adjusted_day = target_day;
            if (tm.tm_wday == 0)        // Sunday to Monday
                adjusted_day = std::min(target_day + 1, last_day);
            else if (tm.tm_wday == 6)   // Saturday to Friday
                adjusted_day = std::max(target_day - 1, 1);

            values.push_back(adjusted_day);
            return;
        }
    }

    // Handle single values (numbers or names)
    int val = parse_field_value(sub, field_type == CRON_MONTH, field_type == CRON_WEEKDAY);
    if (val != -1)
        values.push_back(val);
}

// Parse cron field into allowed values (unified implementation)
LOCAL std::vector<int> parse_field(const std::string& field,
    int field_type,
    const CurrentTimeInfo& time_info)
{
    std::vector<int> values;
    std::vector<std::string> sub_fields;
    std::stringstream ss(field);
    std::string sub;

    // Split by comma (list values)
    while (std::getline(ss, sub, ','))
    {
        if (!sub.empty())
            sub_fields.push_back(sub);
    }

    // Parse each sub-field using unified logic
    for (const std::string& sub : sub_fields)
    {
        parse_sub_field(sub, field_type, time_info, values);
    }

    return values;
}

// Validate single cron field
LOCAL bool validate_field(const std::string& field, int field_type)
{
    if (field.empty()) return false;

    // Allowed special characters by field type
    std::string allowed_chars;
    switch (field_type)
    {
    case CRON_DAY:     allowed_chars = "*,-/LW";  break;
    case CRON_WEEKDAY: allowed_chars = "*,-/L#";  break;
    default:           allowed_chars = "*,-/";
    }

    // Check for invalid characters
    for (char c : field)
    {
        if ((allowed_chars.find(c) == std::string::npos)
            && !std::isalnum(static_cast<unsigned char>(c)))
            return false;
    }

    // Split and validate sub-fields
    std::vector<std::string> sub_fields;
    std::stringstream ss(field);
    std::string sub;
    while (std::getline(ss, sub, ','))
    {
        if (sub.empty()) return false; // Empty sub-field (e.g., ",12" or "12,")

        // Validate step syntax
        size_t slash_pos = sub.find('/');
        if (slash_pos != std::string::npos)
        {
            std::string step_str = sub.substr(slash_pos + 1);
            if (step_str.empty() || !is_all_digits(step_str) || std::stoi(step_str) <= 0)
                return false;
        }

        // Validate range syntax
        size_t dash_pos = sub.find('-');
        if (dash_pos != std::string::npos)
        {
            if (dash_pos == 0 || dash_pos == sub.size() - 1)
                return false; // Invalid range (e.g., "-12" or "12-")
        }

        // Validate # syntax (weekday only)
        if (field_type == CRON_WEEKDAY)
        {
            size_t hash_pos = sub.find('#');
            if (hash_pos != std::string::npos)
            {
                if (hash_pos == 0 || hash_pos == sub.size() - 1)
                    return false; // Invalid # (e.g., "#2" or "3#")

                std::string nth_str = sub.substr(hash_pos + 1);
                if (!is_all_digits(nth_str) || std::stoi(nth_str) < 1 || std::stoi(nth_str) > 5)
                    return false;
            }
        }

        // Validate W syntax (day only)
        if (field_type == CRON_DAY && sub.find('W') != std::string::npos)
        {
            size_t w_pos = sub.find('W');
            if (w_pos == 0 || w_pos != sub.size() - 1)
                return false; // Invalid W (e.g., "W15" or "15Wx")

            std::string day_str = sub.substr(0, w_pos);
            if (!is_all_digits(day_str) || std::stoi(day_str) < 1 || std::stoi(day_str) > 31)
                return false;
        }

        // Validate single values
        if (sub != "*" && sub != "L" &&
            sub.find('/') == std::string::npos &&
            sub.find('-') == std::string::npos &&
            sub.find('#') == std::string::npos &&
            sub.find('W') == std::string::npos)
        {
            int val = parse_field_value(sub, field_type == CRON_MONTH, field_type == CRON_WEEKDAY);
            if (val == -1) return false;

            // Check value range
            auto [min, max] = get_field_range(field_type);
            if (val < min || val > max)
                return false;
        }

        sub_fields.push_back(sub);
    }

    return true;
}

// Validate standard 5-field cron expression
LOCAL bool validate_cron(const std::string& cron)
{
    std::vector<std::string> fields = utils::split(cron);
    if (fields.size() != CRON_FIELD_NUM) return false;

    return validate_field(fields[CRON_MINUTE], CRON_MINUTE) &&
        validate_field(fields[CRON_HOUR], CRON_HOUR) &&
        validate_field(fields[CRON_DAY], CRON_DAY) &&
        validate_field(fields[CRON_MONTH], CRON_MONTH) &&
        validate_field(fields[CRON_WEEKDAY], CRON_WEEKDAY);
}

// Overload: Support const char*
LOCAL bool validate_cron(const char* cronExpr)
{
    return validate_cron(std::string(cronExpr));
}

// Check if current time matches cron expression
LOCAL bool is_current_time_matching(const std::string& cron)
{
    if (!validate_cron(cron)) return false;

    std::vector<std::string> fields = utils::split(cron);
    CurrentTimeInfo time_info = get_current_time_info();

    // Parse allowed values for each field
    std::vector<std::vector<int>> allowed_values;
    allowed_values.push_back(parse_field(fields[CRON_MINUTE], CRON_MINUTE, time_info));
    allowed_values.push_back(parse_field(fields[CRON_HOUR], CRON_HOUR, time_info));
    allowed_values.push_back(parse_field(fields[CRON_DAY], CRON_DAY, time_info));
    allowed_values.push_back(parse_field(fields[CRON_MONTH], CRON_MONTH, time_info));
    allowed_values.push_back(parse_field(fields[CRON_WEEKDAY], CRON_WEEKDAY, time_info));

    // Lambda to check value in allowed list
    auto is_value_allowed = [&](int field_index, int value) {
        return std::find(allowed_values[field_index].begin(),
            allowed_values[field_index].end(),
            value) != allowed_values[field_index].end();
        };

    // Check basic time components
    if (!is_value_allowed(CRON_MINUTE, time_info.minute)) return false;
    if (!is_value_allowed(CRON_HOUR, time_info.hour))     return false;
    if (!is_value_allowed(CRON_DAY, time_info.day))       return false;
    if (!is_value_allowed(CRON_MONTH, time_info.month))   return false;

    // Special handling for weekday L syntax
    if (fields[CRON_WEEKDAY].find("L") != std::string::npos)
    {
        int last_weekday = get_last_weekday_of_month(time_info.year, time_info.month, time_info.weekday);
        if (time_info.day != last_weekday) return false;
    }
    else if (!is_value_allowed(CRON_WEEKDAY, time_info.weekday))
    {
        return false;
    }

    return true;
}

LOCAL void to_json(nlohmann::json& j, const CronTask& task) 
{
    j = 
    {
        {"taskName", task.taskName},
        {"cronExpr", task.cronExpr},
        {"taskPath", task.taskPath}
    };
}

LOCAL void from_json(const nlohmann::json& j, CronTask& task) 
{
    j.at("taskName").get_to(task.taskName);
    j.at("cronExpr").get_to(task.cronExpr);
    j.at("taskPath").get_to(task.taskPath);
    task.lastExecMinute = -1;
    task.lastExecHour   = -1;
    task.lastExecDay    = -1;
}

LOCAL bool validate_task(const CronTask& task) 
{
    if (task.taskName.empty()) 
    {
        LOG_ERROR("Task name is empty");
        return false;
    }
    if (!validate_cron(task.cronExpr)) 
    {
        LOG_ERROR("Invalid cron for task [%s]", task.taskName.c_str());
        return false;
    }
    if (task.taskPath.empty()) 
    {
        LOG_ERROR("Task path empty for [%s]", task.taskName.c_str());
        return false;
    }
    return true;
}

LOCAL bool writeCronTaskConfig(const std::string& filename, const CronTaskMap& tasks) {
    try 
    {
        for (const auto& [key, task] : tasks)
        {
            if (!validate_task(task)) return false;
        }

        std::ofstream ofs(filename);
        if (!ofs)
        {
            LOG_ERROR("Cannot write to %s", filename.c_str());
            return false;
        }
        ofs << nlohmann::json(tasks).dump(4);
        return true;
    }
    catch (const std::exception& e)
    {
        LOG_ERROR("Write failed: %s", e.what());
        return false;
    }
}

LOCAL bool readCronTaskConfig(const std::string& filename, CronTaskMap& tasks) {
    try 
    {
        std::ifstream ifs(filename);
        if (!ifs)
        {
            LOG_ERROR("Cannot read %s", filename.c_str());
            return false;
        }
        nlohmann::json j;
        ifs >> j;

        tasks = j.get<CronTaskMap>();

        for (auto it = tasks.begin(); it != tasks.end();)
        {
            const auto& [username, user] = *it;
            if (!validate_task(it->second))
            {
                tasks.erase(it++);
            }
            else
            {
                ++it;
            }
        }
        return true;
    } 
    catch (const std::exception& e) 
    {
        LOG_ERROR("Read failed: %s", e.what());
        return false;
    }
}

LOCAL void executeJob(void* arg)
{
    if (arg == nullptr)
    {
        LOG_ERROR("Task path is null");
        return;
    }
    std::string taskPath = static_cast<char*>(arg);
    LOG_INFO("Executing cron task: %s", taskPath.c_str());
    free(arg);

#ifdef _WIN32
    std::ostringstream cmdStream;
    cmdStream << "cmd.exe /c " << DQUOTES << taskPath << DQUOTES;
    std::string cmd = cmdStream.str();
#else
    std::string cmd = taskPath;
#endif

    system(cmd.c_str());
}
void CronManager::cronCheckJobs()
{
    m_isRunning.store(true);
    while (m_isRunning.load())
    {
        auto cycle_start = std::chrono::high_resolution_clock::now();
        {
            CurrentTimeInfo now = get_current_time_info();
            int currentMin = now.minute;
            int currentHour = now.hour;
            int currentDay = now.day;

            std::lock_guard<std::mutex> lock(m_objectLock);
            for (auto& job : m_jobs)
            {
                if (!m_isRunning.load())
                {
                    break;
                }
                if (is_current_time_matching(job.second.cronExpr))
                {
                    bool isSameMinute = (job.second.lastExecMinute == currentMin)
                        && (job.second.lastExecHour == currentHour)
                        && (job.second.lastExecDay == currentDay);

                    if (isSameMinute) continue;

                    char* taskPath = FMT_POSIX_CALL(strdup)(job.second.taskPath.c_str());
                    if (taskPath == nullptr)
                    {
                        LOG_ERROR("Failed to allocate memory for task path");
                        continue;
                    }
                    if (jobAdd(reinterpret_cast<VOIDFUNCPTR>(executeJob), taskPath) != OK)
                    {
                        LOG_ERROR("Failed to add job to queue: %s", job.second.taskPath.c_str());
                        free(taskPath);
                    }
                    else
                    {
                        job.second.lastExecMinute = currentMin;
                        job.second.lastExecHour = currentHour;
                        job.second.lastExecDay = currentDay;
                    }
                }
            }
        }
        auto current_time = std::chrono::high_resolution_clock::now();
        auto cycle_total_us = std::chrono::duration_cast<std::chrono::microseconds>(current_time - cycle_start).count();
        double wait_seconds = 1.0 - (cycle_total_us / 1000000.0);

#ifdef _DEBUG
        LOG_DBG("Cron cycle total time: %d us (target: 1000000 us)", cycle_total_us);
        LOG_DBG("Calculated wait time: %.6f seconds", wait_seconds);
#endif
        utils::taskDelay(wait_seconds);
    }
}

STATUS  CronManager::dump(TextTable& outMsg)
{
 return dump(outMsg, true);
}

STATUS CronManager::dump(TextTable& outMsg, bool isDump)
{
    std::lock_guard<std::mutex> lock(m_objectLock);
    outMsg.setTableName("List all cron jobs");
    outMsg.addHeader("Name");
    outMsg.addHeader("CronExpr");
    if(isDump)
    {
        outMsg.addHeader("LM");
        outMsg.addHeader("LH");
        outMsg.addHeader("LD");
    }
    outMsg.addHeader("Task");
    outMsg.endOfRow();
    for (auto& it : m_jobs)
    {
        outMsg.add(it.first);
        outMsg.add(it.second.cronExpr);
        if(isDump)
        {
            outMsg.add(std::to_string(it.second.lastExecMinute));
            outMsg.add(std::to_string(it.second.lastExecHour));
            outMsg.add(std::to_string(it.second.lastExecDay));
        }
        outMsg.add(it.second.taskPath);
        outMsg.endOfRow();
    }
    return OK;
}
PROCESS_IMPL_DESC(CronManager, process)
{
    PROCESS_BEGIN()
    PROCESS_CALL(CMD_SYS_SHUTDOWN, sysShutdown)
    PROCESS_CALL(CMD_CRON_ADD, addJob)
    PROCESS_CALL(CMD_CRON_REMOVE, removeJob)
    PROCESS_CALL(CMD_CRON_LIST, jobList)
    PROCESS_END(RET_ERROR)
}

PROCESS_IMPL_DESC(CronManager, jobList)
{
    return dump(outMsg, false);
}

PROCESS_IMPL_DESC(CronManager, addJob)
{
    COND_CHECK_RET_ERROR(!reqArgs.has("name"));
    COND_CHECK_RET_ERROR(!reqArgs.has("cron"));
    COND_CHECK_RET_ERROR(!reqArgs.has("task"));

    std::string name = reqArgs.get("name");
    std::string cronExpr = reqArgs.get("cron");
    std::string taskPath = reqArgs.get("task");

    COND_CHECK_RET_ERROR(name.empty());
    COND_CHECK_RET_ERROR(cronExpr.empty());
    COND_CHECK_RET_ERROR(taskPath.empty());

    CronTask cronTask = {name, cronExpr , taskPath, -1, -1, -1};
    std::lock_guard<std::mutex> lock(m_objectLock);
    auto it = m_jobs.find(name);
    COND_CHECK_RET_ERROR(it != m_jobs.end());
    m_jobs[name] = cronTask;
    LOG_INFO("Added cron job %s: %s -> %s", name.c_str(), cronExpr.c_str(), taskPath.c_str());
    if(!writeCronTaskConfig(utils::format("%s/%s",DEFAULT_CONFIG_PATH, DEFAULT_CRON_FILE).c_str(), m_jobs))
    {
        LOG_ERROR("Saving cron task config fail");
    }

    return OK;
}
PROCESS_IMPL_DESC(CronManager, removeJob)
{
    COND_CHECK_RET_ERROR(!reqArgs.has("name"));
    std::string name = reqArgs.get("name");

    COND_CHECK_RET_ERROR(name.empty());
    std::lock_guard<std::mutex> lock(m_objectLock);
    auto it = m_jobs.find(name);

    COND_CHECK_RET_ERROR(it == m_jobs.end());
    m_jobs.erase(it);
    if(!writeCronTaskConfig(utils::format("%s/%s",DEFAULT_CONFIG_PATH, DEFAULT_CRON_FILE), m_jobs))
    {
        LOG_ERROR("Saving cron task config fail");
    }
    return OK;
}

PROCESS_IMPL_DESC(CronManager, sysShutdown)
{
    return destory();
}
STATUS  CronManager::preInit()
{
    m_isRunning.store(false);
    utils::mkdirPath(DEFAULT_CONFIG_PATH);
    readCronTaskConfig(utils::format("%s/%s",DEFAULT_CONFIG_PATH, DEFAULT_CRON_FILE), m_jobs);
    return OK;
}

LOCAL void cronTask(void* pobjPara)
{
    CronManager* pThis = reinterpret_cast<CronManager*>(pobjPara);
    pThis->cronCheckJobs();
};

STATUS  CronManager::postInit()
{
    COND_CHECK_RET_ERROR(registerMessageListener(MODULE_CRON_MGR) != OK);
    COND_CHECK_RET_ERROR((GET_FRAMEWORK_MGR->callObjectMethod<cli::cliManager, STATUS>
        (MODULE_CLI_MGR, &cli::cliManager::cliCmdRegister,
            &gCronCommands[0], size_t(NELEMENTS(gCronCommands)))) != OK);
    COND_CHECK_RET_ERROR(CREATE_OBJTASK("CronTask", reinterpret_cast<FUNCPTR>(cronTask), this) != OK);

    return OK;
}

STATUS CronManager::destory()
{
    std::lock_guard<std::mutex> lock(m_objectLock);
    m_isRunning.store(false);
    m_jobs.clear();
    return OK;
}
REG_TO_FRAMEWORK(CronManager, MODULE_CRON_MGR);